#include "StdAfx.h"
#include "EventQueue.h"

using namespace BAA;

EventQueue * EventQueue::pInstance = 0;// initialize pointer

EventQueue * EventQueue::getInstance(){
	if( pInstance == NULL ){
		EventQueue::pInstance = new EventQueue();
		return pInstance;
	}else{
		return pInstance;
	}
}

EventQueue::EventQueue(void)
{
	in_events.clear();
	out_events.clear();
}

EventQueue::~EventQueue(void)
{
}

/*
	processQueues is responsible for dropping the appropriate events from the
	input and output queues

	appropriate events are determined based on a number of factors including:
		elapsed time
		urgency
		agents involved (if all agents have processed it, drop it)
		targets
*/
void EventQueue::processQueues(){
	FILETIME ft;
    SYSTEMTIME st;

    GetSystemTime(&st);              // Gets the current system time
    SystemTimeToFileTime(&st, &ft);  // Converts the current system time to file time format
	__int64 u_l;
	memcpy(&u_l, &ft, sizeof(__int64) );
	u_l = u_l / 10000;

	//process in queue
	unsigned int size = in_events.size();
	unsigned int i = 0;
	while( i != size ){
		if( u_l - in_events[i]->getTimestamp() > 300){ // 300ms
			//remove it from the queue
			delete in_events[i];
			removeIncomingEvent( in_events[i] );
			size = in_events.size();
		}else{
			i++;
		}
	}

	//process out queue
	size = out_events.size();
	i = 0;
	while( i != size ){
		if( u_l - out_events[i]->getTimestamp() > 300){ // 300ms
			//remove it from the queue
			delete out_events[i];
			removeOutgoingEvent( out_events[i] );
			size = out_events.size();
		}else{
			i++;
		}
	}

	return;
}

/*
	addIncomingEvent adds an event from the external system into the incoming event queue
		to be processed by the appropriate agents

	incoming events might be of the form:
		agent has finished action x
		agent has been interrupted
		agent has died (oops!)
*/
void EventQueue::addIncomingEvent(Event * e){
	in_events.push_back(e);
}

/*
	addOutgoingEvent adds an event from the AI system into the outgoing event queue
		to be processed by the game engine

	incoming events might be of the form:
		agent wants to move to location x,y,z
		agent wants to perform animation "shopping"
		agent wants to idle
*/
void EventQueue::addOutgoingEvent(Event * e){
	out_events.push_back(e);
}

//removeIncomingEvent removes an event from the incoming queue
bool EventQueue::removeIncomingEvent(Event * e){
	//find the index of event e
	std::vector<Event *>::iterator iter = in_events.begin();
	int count = 0;
	while( (*iter) != e ){
		count += 1;
		iter++;

		if(iter == in_events.end()){
			return false;
		}
	}

	std::cout << "Index of event e in in_events: " << count << std::endl;
	//remove e from the vector
	in_events.erase(iter);
	return true;
}

//removeOutgoingEvent removes an event from the outgoing queue
bool EventQueue::removeOutgoingEvent(Event * e){
	//find the index of event e
	std::vector<Event *>::iterator iter = out_events.begin();
	int count = 0;
	while( (*iter) != e ){
		count += 1;
		iter++;

		if(iter == out_events.end()){
			return false;
		}
	}

	std::cout << "Index of event e in in_events: " << count << std::endl;
	//remove e from the vector
	out_events.erase(iter);
	return true;
}

std::vector<Event *> * EventQueue::in(){
	return &in_events;
}

std::vector<Event *> * EventQueue::out(){
	return &out_events;
}

void EventQueue::testClass(){
	/*
	Event * a; Event * b; Event * c; Event * d;
	a = new Event(0.0f, 0.1f, 0.2f);
	b = new Event(0.1f, 0.1f, 0.2f);
	c = new Event(0.2f, 0.1f, 0.2f);
	d = new Event(0.3f, 0.1f, 0.2f);

	this->addIncomingEvent(a);
	this->addIncomingEvent(b);
	this->addIncomingEvent(c);
	this->addIncomingEvent(d);

	this->removeIncomingEvent(c);
	this->addIncomingEvent(c);

	unsigned int size = in_events.size();

	this->processQueues();

	delete a;
	delete b;
	delete c;
	delete d;
	*/
}